// 安全工具类
// 实现各种安全相关的功能和方法

import { securityConfig } from '../config/securityConfig.js';

// 密码工具类
export const passwordUtils = {
  /**
   * 验证密码强度
   * @param {string} password - 要验证的密码
   * @param {string} [username] - 用户名（用于检查密码是否包含用户名）
   * @returns {object} 密码强度验证结果
   */
  validatePassword(password, username = '') {
    const { passwordRequirements } = securityConfig.validation;
    const errors = [];
    
    // 检查密码长度
    if (password.length < passwordRequirements.minLength) {
      errors.push(`密码长度必须至少为 ${passwordRequirements.minLength} 个字符`);
    }
    
    // 检查是否包含大写字母
    if (passwordRequirements.requireUppercase && !/[A-Z]/.test(password)) {
      errors.push('密码必须包含至少一个大写字母');
    }
    
    // 检查是否包含小写字母
    if (passwordRequirements.requireLowercase && !/[a-z]/.test(password)) {
      errors.push('密码必须包含至少一个小写字母');
    }
    
    // 检查是否包含数字
    if (passwordRequirements.requireNumbers && !/\d/.test(password)) {
      errors.push('密码必须包含至少一个数字');
    }
    
    // 检查是否包含特殊字符
    if (passwordRequirements.requireSpecialChars) {
      const specialCharsRegex = new RegExp(`[${passwordRequirements.specialChars.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}]`);
      if (!specialCharsRegex.test(password)) {
        errors.push(`密码必须包含至少一个特殊字符（${passwordRequirements.specialChars}）`);
      }
    }
    
    // 检查常见密码
    if (passwordRequirements.disallowedPasswords.includes(password.toLowerCase())) {
      errors.push('密码不能是常见密码');
    }
    
    // 检查是否包含用户名
    if (passwordRequirements.checkUsernameInPassword && username && password.toLowerCase().includes(username.toLowerCase())) {
      errors.push('密码不能包含用户名');
    }
    
    return {
      isValid: errors.length === 0,
      errors
    };
  },
  
  /**
   * 计算密码强度分数
   * @param {string} password - 要评分的密码
   * @returns {number} 密码强度分数（0-100）
   */
  calculatePasswordStrength(password) {
    let score = 0;
    
    // 长度分数（最多40分）
    score += Math.min(password.length * 4, 40);
    
    // 复杂度分数
    if (/[A-Z]/.test(password)) score += 10;
    if (/[a-z]/.test(password)) score += 10;
    if (/\d/.test(password)) score += 10;
    if (/[^A-Za-z0-9]/.test(password)) score += 10;
    
    // 重复字符检查
    const uniqueChars = new Set(password).size;
    score += Math.min((uniqueChars / password.length) * 20, 20);
    
    return Math.min(score, 100);
  },
  
  /**
   * 生成密码强度提示
   * @param {number} strength - 密码强度分数
   * @returns {object} 密码强度提示信息
   */
  getPasswordStrengthInfo(strength) {
    if (strength < 30) {
      return { level: 'weak', message: '弱密码，请增加复杂度', color: 'red' };
    } else if (strength < 60) {
      return { level: 'medium', message: '中等强度', color: 'orange' };
    } else if (strength < 80) {
      return { level: 'strong', message: '强度良好', color: 'yellow' };
    } else {
      return { level: 'very_strong', message: '强密码，很安全', color: 'green' };
    }
  },
  
  /**
   * 生成随机密码
   * @param {number} length - 密码长度
   * @param {object} options - 密码选项
   * @returns {string} 生成的随机密码
   */
  generateRandomPassword(length = 12, options = {}) {
    const { 
      includeUppercase = true, 
      includeLowercase = true, 
      includeNumbers = true, 
      includeSpecialChars = true
    } = options;
    
    let charset = '';
    const lowerChars = 'abcdefghijklmnopqrstuvwxyz';
    const upperChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    const numberChars = '0123456789';
    const specialChars = securityConfig.validation.passwordRequirements.specialChars;
    
    if (includeLowercase) charset += lowerChars;
    if (includeUppercase) charset += upperChars;
    if (includeNumbers) charset += numberChars;
    if (includeSpecialChars) charset += specialChars;
    
    let password = '';
    for (let i = 0; i < length; i++) {
      password += charset.charAt(Math.floor(Math.random() * charset.length));
    }
    
    return password;
  }
};

// 输入验证工具类
export const validationUtils = {
  /**
   * 验证电子邮件
   * @param {string} email - 电子邮件地址
   * @returns {boolean} 是否有效
   */
  isValidEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  },
  
  /**
   * 验证电话号码
   * @param {string} phone - 电话号码
   * @returns {boolean} 是否有效
   */
  isValidPhone(phone) {
    // 支持中国手机号和国际电话号码格式
    const phoneRegex = /^1[3-9]\d{9}$|^\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$/;
    return phoneRegex.test(phone);
  },
  
  /**
   * 验证用户名
   * @param {string} username - 用户名
   * @returns {boolean} 是否有效
   */
  isValidUsername(username) {
    // 用户名规则：4-20个字符，只能包含字母、数字、下划线和中文
    const usernameRegex = /^[a-zA-Z0-9_\u4e00-\u9fa5]{4,20}$/;
    return usernameRegex.test(username);
  },
  
  /**
   * 清理输入内容
   * @param {string} input - 输入内容
   * @returns {string} 清理后的内容
   */
  sanitizeInput(input) {
    if (typeof input !== 'string') return input;
    
    let cleaned = input;
    
    // 移除HTML标签
    if (securityConfig.validation.inputRules.removeHtmlTags) {
      cleaned = cleaned.replace(/<[^>]*>/g, '');
    }
    
    // 转义特殊字符
    if (securityConfig.validation.inputRules.escapeSpecialChars) {
      const escapeMap = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
      };
      cleaned = cleaned.replace(/[&<>"']/g, char => escapeMap[char]);
    }
    
    // 限制长度
    if (securityConfig.validation.inputRules.maxInputLength) {
      cleaned = cleaned.substring(0, securityConfig.validation.inputRules.maxInputLength);
    }
    
    // 限制字符集
    if (securityConfig.validation.inputRules.restrictInputChars && 
        securityConfig.validation.inputRules.allowedCharsPattern) {
      cleaned = cleaned.replace(securityConfig.validation.inputRules.allowedCharsPattern, '');
    }
    
    return cleaned;
  },
  
  /**
   * 验证URL
   * @param {string} url - URL地址
   * @returns {boolean} 是否有效
   */
  isValidUrl(url) {
    try {
      new URL(url);
      return true;
    } catch (error) {
      return false;
    }
  },
  
  /**
   * 验证身份证号
   * @param {string} idCard - 身份证号
   * @returns {boolean} 是否有效
   */
  isValidIdCard(idCard) {
    // 简单的身份证号验证
    const idCardRegex = /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
    return idCardRegex.test(idCard);
  }
};

// XSS防护工具类
export const xssUtils = {
  /**
   * 转义HTML
   * @param {string} str - 要转义的字符串
   * @returns {string} 转义后的字符串
   */
  escapeHtml(str) {
    if (typeof str !== 'string') return str;
    
    const div = document.createElement('div');
    div.textContent = str;
    return div.innerHTML;
  },
  
  /**
   * 反转义HTML
   * @param {string} str - 要反转义的字符串
   * @returns {string} 反转义后的字符串
   */
  unescapeHtml(str) {
    if (typeof str !== 'string') return str;
    
    const div = document.createElement('div');
    div.innerHTML = str;
    return div.textContent || div.innerText || '';
  },
  
  /**
   * 安全设置innerHTML
   * @param {HTMLElement} element - DOM元素
   * @param {string} html - HTML内容
   */
  setSafeHtml(element, html) {
    if (!element || !(element instanceof HTMLElement)) return;
    
    // 移除潜在的危险标签和属性
    const sanitizedHtml = this.sanitizeHtml(html);
    element.innerHTML = sanitizedHtml;
    
    // 清理事件处理程序
    this.cleanupEventHandlers(element);
  },
  
  /**
   * 清理HTML内容
   * @param {string} html - HTML内容
   * @returns {string} 清理后的HTML
   */
  sanitizeHtml(html) {
    // 移除脚本标签
    html = html.replace(/<script[^>]*>.*?<\/script>/gi, '');
    
    // 移除事件处理属性
    html = html.replace(/on\w+\s*=\s*["\'][^"\']*["\']/gi, '');
    
    // 移除style属性中的潜在危险内容
    html = html.replace(/style\s*=\s*["\']([^"\']*)["\']/gi, (match, style) => {
      // 移除javascript: urls
      const safeStyle = style.replace(/\bjavascript:[^;]+;/gi, '');
      return `style="${safeStyle}"`;
    });
    
    // 移除iframe标签
    html = html.replace(/<iframe[^>]*>.*?<\/iframe>/gi, '');
    
    return html;
  },
  
  /**
   * 清理DOM元素中的事件处理程序
   * @param {HTMLElement} element - DOM元素
   */
  cleanupEventHandlers(element) {
    // 克隆并替换元素以移除所有事件监听器
    const clone = element.cloneNode(true);
    element.parentNode.replaceChild(clone, element);
  }
};

// CSRF防护工具类
export const csrfUtils = {
  /**
   * 从Cookie获取CSRF令牌
   * @returns {string|null} CSRF令牌
   */
  getCsrfToken() {
    const cookieName = securityConfig.csrf.cookieName;
    const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
    return match ? match[2] : null;
  },
  
  /**
   * 设置CSRF令牌到请求头
   * @param {XMLHttpRequest|RequestInit} request - 请求对象
   */
  setCsrfToken(request) {
    if (!securityConfig.csrf.enabled) return;
    
    const tokenName = securityConfig.csrf.tokenName;
    const token = this.getCsrfToken();
    
    if (token) {
      if (request instanceof XMLHttpRequest) {
        request.setRequestHeader(tokenName, token);
      } else if (request.headers) {
        request.headers[tokenName] = token;
      }
    }
  },
  
  /**
   * 生成CSRF令牌
   * @returns {string} 生成的令牌
   */
  generateCsrfToken() {
    const length = securityConfig.csrf.tokenLength;
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let token = '';
    
    for (let i = 0; i < length; i++) {
      token += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    
    return token;
  },
  
  /**
   * 验证CSRF令牌
   * @param {string} token - 要验证的令牌
   * @returns {boolean} 是否有效
   */
  validateCsrfToken(token) {
    const storedToken = this.getCsrfToken();
    return token && storedToken && token === storedToken;
  }
};

// 认证和授权工具类
export const authUtils = {
  /**
   * 检查用户是否已登录
   * @returns {boolean} 是否已登录
   */
  isAuthenticated() {
    return !!localStorage.getItem('authToken') || !!sessionStorage.getItem('authToken');
  },
  
  /**
   * 获取认证令牌
   * @returns {string|null} 认证令牌
   */
  getAuthToken() {
    return localStorage.getItem('authToken') || sessionStorage.getItem('authToken');
  },
  
  /**
   * 设置认证令牌
   * @param {string} token - 认证令牌
   * @param {boolean} rememberMe - 是否记住登录
   */
  setAuthToken(token, rememberMe = false) {
    if (rememberMe) {
      localStorage.setItem('authToken', token);
    } else {
      sessionStorage.setItem('authToken', token);
    }
  },
  
  /**
   * 移除认证令牌
   */
  removeAuthToken() {
    localStorage.removeItem('authToken');
    sessionStorage.removeItem('authToken');
  },
  
  /**
   * 检查用户权限
   * @param {string|array} requiredPermissions - 要求的权限
   * @returns {boolean} 是否有权限
   */
  hasPermission(requiredPermissions) {
    const userPermissions = this.getUserPermissions();
    
    if (!userPermissions || userPermissions.length === 0) {
      return false;
    }
    
    // 如果用户有全部权限
    if (userPermissions.includes('*')) {
      return true;
    }
    
    if (typeof requiredPermissions === 'string') {
      return userPermissions.includes(requiredPermissions);
    }
    
    if (Array.isArray(requiredPermissions)) {
      return requiredPermissions.every(permission => userPermissions.includes(permission));
    }
    
    return false;
  },
  
  /**
   * 获取用户权限
   * @returns {array} 用户权限列表
   */
  getUserPermissions() {
    try {
      const permissionsStr = localStorage.getItem('userPermissions') || sessionStorage.getItem('userPermissions');
      return permissionsStr ? JSON.parse(permissionsStr) : [];
    } catch (error) {
      console.error('获取用户权限失败:', error);
      return [];
    }
  },
  
  /**
   * 设置用户权限
   * @param {array} permissions - 权限列表
   * @param {boolean} rememberMe - 是否记住登录
   */
  setUserPermissions(permissions, rememberMe = false) {
    const permissionsStr = JSON.stringify(permissions);
    
    if (rememberMe) {
      localStorage.setItem('userPermissions', permissionsStr);
    } else {
      sessionStorage.setItem('userPermissions', permissionsStr);
    }
  },
  
  /**
   * 检查用户角色
   * @param {string|array} roles - 要检查的角色
   * @returns {boolean} 是否有指定角色
   */
  hasRole(roles) {
    const userRoles = this.getUserRoles();
    
    if (!userRoles || userRoles.length === 0) {
      return false;
    }
    
    if (typeof roles === 'string') {
      return userRoles.includes(roles);
    }
    
    if (Array.isArray(roles)) {
      return roles.some(role => userRoles.includes(role));
    }
    
    return false;
  },
  
  /**
   * 获取用户角色
   * @returns {array} 用户角色列表
   */
  getUserRoles() {
    try {
      const rolesStr = localStorage.getItem('userRoles') || sessionStorage.getItem('userRoles');
      return rolesStr ? JSON.parse(rolesStr) : [];
    } catch (error) {
      console.error('获取用户角色失败:', error);
      return [];
    }
  },
  
  /**
   * 清除用户认证信息
   */
  clearAuthInfo() {
    this.removeAuthToken();
    localStorage.removeItem('userPermissions');
    sessionStorage.removeItem('userPermissions');
    localStorage.removeItem('userRoles');
    sessionStorage.removeItem('userRoles');
    localStorage.removeItem('userInfo');
    sessionStorage.removeItem('userInfo');
  }
};

// 加密和编码工具类
export const cryptoUtils = {
  /**
   * Base64编码
   * @param {string} str - 要编码的字符串
   * @returns {string} Base64编码后的字符串
   */
  base64Encode(str) {
    if (typeof str !== 'string') return '';
    return btoa(unescape(encodeURIComponent(str)));
  },
  
  /**
   * Base64解码
   * @param {string} encodedStr - Base64编码的字符串
   * @returns {string} 解码后的字符串
   */
  base64Decode(encodedStr) {
    if (typeof encodedStr !== 'string') return '';
    try {
      return decodeURIComponent(escape(atob(encodedStr)));
    } catch (error) {
      console.error('Base64解码失败:', error);
      return '';
    }
  },
  
  /**
   * 生成随机ID
   * @param {number} length - ID长度
   * @returns {string} 随机ID
   */
  generateRandomId(length = 16) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let id = '';
    
    for (let i = 0; i < length; i++) {
      id += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    
    return id;
  },
  
  /**
   * 生成唯一标识符
   * @returns {string} UUID
   */
  generateUuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      const r = Math.random() * 16 | 0;
      const v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  },
  
  /**
   * 脱敏敏感数据
   * @param {string} data - 敏感数据
   * @param {string} type - 数据类型
   * @returns {string} 脱敏后的数据
   */
  maskSensitiveData(data, type) {
    if (!data) return data;
    
    switch (type) {
      case 'phone':
        // 手机号脱敏，保留前3后4
        return data.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
      
      case 'email':
        // 邮箱脱敏
        return data.replace(/(.{2})(.*)(@.*)/, '$1****$3');
      
      case 'idcard':
        // 身份证脱敏
        return data.replace(/(\d{6})\d{8}(\d{4})/, '$1********$2');
      
      case 'bankcard':
        // 银行卡脱敏
        return data.replace(/(\d{4})\d{8,12}(\d{4})/, '$1********$2');
      
      case 'password':
        // 密码完全脱敏
        return '********';
      
      default:
        // 其他数据脱敏，保留前2后2
        if (data.length <= 4) return '****';
        const first = data.substring(0, 2);
        const last = data.substring(data.length - 2);
        const mask = '*'.repeat(data.length - 4);
        return first + mask + last;
    }
  }
};

// 安全存储工具类
export const storageUtils = {
  /**
   * 安全存储数据
   * @param {string} key - 存储键
   * @param {any} value - 存储值
   * @param {boolean} useSession - 是否使用sessionStorage
   */
  setItem(key, value, useSession = false) {
    const storage = useSession ? sessionStorage : localStorage;
    const stringValue = typeof value === 'string' ? value : JSON.stringify(value);
    
    try {
      storage.setItem(key, stringValue);
    } catch (error) {
      console.error('存储数据失败:', error);
    }
  },
  
  /**
   * 安全获取数据
   * @param {string} key - 存储键
   * @param {boolean} useSession - 是否使用sessionStorage
   * @returns {any} 存储的值
   */
  getItem(key, useSession = false) {
    const storage = useSession ? sessionStorage : localStorage;
    
    try {
      const value = storage.getItem(key);
      if (value === null) return null;
      
      // 尝试解析JSON
      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      console.error('获取数据失败:', error);
      return null;
    }
  },
  
  /**
   * 安全移除数据
   * @param {string} key - 存储键
   * @param {boolean} useSession - 是否使用sessionStorage
   */
  removeItem(key, useSession = false) {
    const storage = useSession ? sessionStorage : localStorage;
    
    try {
      storage.removeItem(key);
    } catch (error) {
      console.error('移除数据失败:', error);
    }
  },
  
  /**
   * 安全清空存储
   * @param {boolean} useSession - 是否清空sessionStorage
   * @param {array} excludeKeys - 排除的键
   */
  clear(useSession = false, excludeKeys = []) {
    const storage = useSession ? sessionStorage : localStorage;
    
    try {
      if (excludeKeys && excludeKeys.length > 0) {
        // 保留指定的键
        const keysToKeep = new Set(excludeKeys);
        const keysToRemove = [];
        
        for (let i = 0; i < storage.length; i++) {
          const key = storage.key(i);
          if (key && !keysToKeep.has(key)) {
            keysToRemove.push(key);
          }
        }
        
        keysToRemove.forEach(key => storage.removeItem(key));
      } else {
        storage.clear();
      }
    } catch (error) {
      console.error('清空存储失败:', error);
    }
  },
  
  /**
   * 检查存储是否可用
   * @param {boolean} useSession - 是否检查sessionStorage
   * @returns {boolean} 是否可用
   */
  isAvailable(useSession = false) {
    const storage = useSession ? sessionStorage : localStorage;
    
    try {
      const testKey = '__storage_test__';
      storage.setItem(testKey, testKey);
      storage.removeItem(testKey);
      return true;
    } catch (error) {
      return false;
    }
  }
};

// 安全HTTP请求工具类
export const httpSecurityUtils = {
  /**
   * 创建安全的fetch请求
   * @param {string} url - 请求URL
   * @param {object} options - 请求选项
   * @returns {Promise} 请求结果
   */
  async secureFetch(url, options = {}) {
    // 确保options存在
    options = options || {};
    options.headers = options.headers || {};
    
    // 添加CSRF令牌
    if (securityConfig.csrf.enabled) {
      csrfUtils.setCsrfToken(options);
    }
    
    // 添加认证令牌
    const authToken = authUtils.getAuthToken();
    if (authToken && !options.headers['Authorization']) {
      options.headers['Authorization'] = `Bearer ${authToken}`;
    }
    
    // 设置内容类型
    if (!options.headers['Content-Type'] && (options.method === 'POST' || options.method === 'PUT' || options.method === 'PATCH')) {
      options.headers['Content-Type'] = 'application/json';
    }
    
    // 清理请求体中的敏感数据
    if (options.body) {
      const sensitiveFields = securityConfig.data.sensitiveFields;
      if (typeof options.body === 'object') {
        options.body = this.maskSensitiveDataInRequest(options.body, sensitiveFields);
        options.body = JSON.stringify(options.body);
      }
    }
    
    try {
      const response = await fetch(url, options);
      
      // 检查响应状态
      if (!response.ok) {
        // 处理认证错误
        if (response.status === 401) {
          authUtils.clearAuthInfo();
          // 可以在这里触发登录跳转
        }
        
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      
      // 检查响应是否为空
      const contentType = response.headers.get('content-type');
      if (contentType && contentType.includes('application/json')) {
        return await response.json();
      }
      
      return await response.text();
    } catch (error) {
      console.error('安全请求失败:', error);
      throw error;
    }
  },
  
  /**
   * 屏蔽请求中的敏感数据
   * @param {object} data - 请求数据
   * @param {array} sensitiveFields - 敏感字段列表
   * @returns {object} 处理后的数据
   */
  maskSensitiveDataInRequest(data, sensitiveFields) {
    if (!data || typeof data !== 'object') return data;
    
    const maskedData = { ...data };
    
    sensitiveFields.forEach(field => {
      if (maskedData.hasOwnProperty(field)) {
        // 创建一个副本，不修改原始数据
        maskedData[field] = cryptoUtils.maskSensitiveData(maskedData[field], field);
      }
    });
    
    return maskedData;
  },
  
  /**
   * 验证响应数据的完整性
   * @param {object} responseData - 响应数据
   * @returns {boolean} 数据是否完整
   */
  validateResponseIntegrity(responseData) {
    // 这里可以实现数据完整性验证逻辑
    // 例如：检查必要字段、验证签名等
    return responseData !== null && typeof responseData === 'object';
  }
};

// 导出所有工具类
export default {
  passwordUtils,
  validationUtils,
  xssUtils,
  csrfUtils,
  authUtils,
  cryptoUtils,
  storageUtils,
  httpSecurityUtils
};